﻿using System;
using System.ComponentModel;
using System.Threading;

namespace ManagedScenarios
{
    /// <summary>
    /// Provides a trivial Monitor.Enter deadlock (low CPU hang)
    /// </summary>
    [Description("Provides a trivial Monitor.Enter deadlock (low hang)")]
    public class DeadlockScenario : IScenario
    {
        public static object SyncLock1 = new LockObject<Worker1>();
        public static object SyncLock2 = new LockObject<Worker2>();

        public void Run(string[] args)
        {
            var thread1 = new Thread(new Worker1().Run);
            var thread2 = new Thread(new Worker2().Run);
            thread1.Start();
            thread2.Start();

            // Technically a thread schedule could be produced that wouldn't create
            // a deadlock. But it's pretty unlikely, given the sleeps etc...

            thread1.Join();
            thread2.Join();
        }

        public class Worker1
        {
            public void Run()
            {
                lock (SyncLock1)
                {
                    Console.WriteLine("Thread1 in outer lock");
                    Thread.Sleep(100);
                    lock (SyncLock2)
                    {
                        Console.WriteLine("Thread1 in inner lock");
                    }
                }
            }
        }

        public class Worker2
        {
            public void Run()
            {
                lock (SyncLock2)
                {
                    Console.WriteLine("Thread2 in outer lock");
                    Thread.Sleep(100);
                    lock (SyncLock1)
                    {
                        Console.WriteLine("Thread2 in inner lock");
                    }
                }
            }
        }
    }
}
